#pragma once
#include "Task.hpp"
#include <iostream>
#include <vector>
#include <exception>
#include <sys/types.h>
#include <sys/wait.h>

class ProcessPool{
public:
    ProcessPool(size_t poolSize, std::vector<Task> Tasks)
    :_Tasks(Tasks)
    {
        //进程的数量不能为0
        if(poolSize == 0){
            throw std::invalid_argument("poolSize is zero");
        }

        //任务vector必须存在
        if(Tasks.size() == 0){
            throw std::invalid_argument("Tasks' Size is zero");
        }

        //创建管道
        if(pipe(_PipeReturnValue) == -1){
            throw std::runtime_error("Failed to create master pipe");
        }

        //创建一批子进程
        for(int i = 0; i < poolSize; i++){
            pid_t ret_pid = fork();
            if(ret_pid == -1){
                throw std::runtime_error("Failed to fork");
            }
            
            //子进程
            if(ret_pid == 0){
                //关闭写duan
                close(_PipeReturnValue[1]);
                
                //进入工作循环
                WorkLoop();

                //退出子进程
                exit(0);
            }else{//父进程
                _Pids.push_back(ret_pid);
            }
        }

        //关闭父进程读端
        close(_PipeReturnValue[0]);
    }

    //析构函数
    ~ProcessPool(){
        //关闭父亲的读端
        if(_PipeReturnValue[1] != -1){
            close(_PipeReturnValue[1]);
        }

        sleep(10);

        //逐一回收子进程
        for(pid_t pid : _Pids){
            waitpid(pid, nullptr, 0);
        }

        //显示回收完毕的消息
        std::cout << "All Workers Have Terminated. ProcessPool Destroyed." << std::endl;
    }

    //发送任务
    void SubmitTask(int taskIndex){
        ssize_t bytesWritten = write(_PipeReturnValue[1], &taskIndex, sizeof(taskIndex));
        if(bytesWritten != sizeof(taskIndex)){
            throw std::runtime_error("Failed to SubmitTask");
        }
    }

private:
    void WorkLoop(){
        while(true){
            int taskIndex = -1;

            //读取任务
            ssize_t bytesRead = read(_PipeReturnValue[0], &taskIndex, sizeof(taskIndex));

            //是否关闭写端
            if(bytesRead <= 0){
                break;
            }

            //验证任务有效性
            if(taskIndex >= 0 && (size_t)taskIndex < _Tasks.size()){
                //执行任务
                _Tasks[taskIndex]();
            }
        }
        //读端关闭，关闭写端
        close(_PipeReturnValue[0]);
    };

    int _PipeReturnValue[2];
    std::vector<Task> _Tasks;
    std::vector<pid_t> _Pids;
};